package v1

import dai.core.base.MyLog
import org.joml.Vector2f
import org.lwjgl.Version
import org.lwjgl.glfw.*
import org.lwjgl.glfw.GLFW.*
import org.lwjgl.opengl.GL
import org.lwjgl.opengl.GLUtil
import org.lwjgl.system.Callback
import org.lwjgl.system.Configuration
import org.lwjgl.system.MemoryStack.stackPush
import org.lwjgl.system.MemoryUtil.NULL
import java.lang.IllegalStateException
import java.lang.RuntimeException


class Window(var width: Float = 800f, var height: Float = 600f, val title: String = "window") {

    companion object {
        const val Debug = true
    }

    var aspect = width / height

    var errHandle: GLFWErrorCallback? = null
    var debugHandle: Callback? = null
    var winHandle = NULL
    var keyboardHandle: GLFWKeyCallback? = null
    var mouseHandle: GLFWMouseButtonCallback? = null
    var cursorPosHandle: GLFWCursorPosCallback? = null
    var cursorEnterHandle: GLFWCursorEnterCallback? = null


    // app ref
    lateinit var app: GameApp
    lateinit var inputMgr: InputMgr

    fun init(gameApp: GameApp) {
        app = gameApp
        MyLog.info("Version:${Version.getVersion()}")

        // 开启debug
        if (Debug) {
            Configuration.DEBUG.set(Debug)
            Configuration.DEBUG_LOADER.set(false)
            Configuration.DEBUG_MEMORY_ALLOCATOR.set(false)
            Configuration.DEBUG_STACK.set(false)
        }

        // 打印错误信息
        errHandle = GLFWErrorCallback.createPrint(System.err).set()

        // 初始化glfw
        if (!glfwInit()) {
            throw IllegalStateException("初始化glfw失败!")
        }

        // 配置glfw
        glfwDefaultWindowHints()
        glfwWindowHint(GLFW_VISIBLE, GLFW_TRUE)
        glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE)

        // set opengl 4.1
        glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4)
        glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1)

        if (Debug) {
            glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE)
        }

        winHandle = glfwCreateWindow(width.toInt(), height.toInt(), title, NULL, NULL)
        if (winHandle == NULL) {
            throw RuntimeException("fail to create window!")
        }
        glfwMakeContextCurrent(winHandle)

        GL.createCapabilities()
        if (Debug) {
            debugHandle = GLUtil.setupDebugMessageCallback(System.out)
        }

        // 开启垂直同步
        glfwSwapInterval(1)
        glfwShowWindow(winHandle)

        inputMgr = InputMgr(this)

        // 注册一堆的回调
        // resize
        glfwSetFramebufferSizeCallback(winHandle) { win, w, h ->
            width = w.toFloat()
            height = h.toFloat()
            aspect = width / height
            // 窗口大小改变
            //TODO: 更新相机
        }

        // 键盘
        keyboardHandle = glfwSetKeyCallback(winHandle) { win, key, scancode, action, mods ->
            inputMgr.keyboardMgr.receiveKeyEvent(key, action)
            // MyLog.info("Key####${Thread.currentThread().name},win:${win},key:${key},scancode:${scancode},action:${action},mods:${mods}")
        }

        // 鼠标
        mouseHandle = glfwSetMouseButtonCallback(winHandle) { win, button, action, mods ->
            inputMgr.mouseMgr.receiverMouseBtnEvent(button, action)
            // MyLog.info("Mouse####${Thread.currentThread().name},win:${win},button:${button},action:${action},mods:${mods}")
        }

        // 鼠标位置事件
        cursorPosHandle = glfwSetCursorPosCallback(winHandle) { win, xpos, ypos ->
            inputMgr.mouseMgr.receiveMouseMove(xpos.toFloat(), ypos.toFloat())
        }

        // 鼠标进入窗口事件
//        cursorEnterHandle = glfwSetCursorEnterCallback(winHandle){win,entered->
//            inputMgr.mouseMgr.valid = entered
//        }
    }

    fun endFrame() {
        glfwSwapBuffers(winHandle)
        glfwPollEvents()
    }

    fun cleanup() {
        errHandle?.free()
        debugHandle?.free()
        keyboardHandle?.free()
        mouseHandle?.free()
        cursorPosHandle?.free()
        cursorEnterHandle?.free()
    }

    fun beginFrame() {
    }
}
